home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload Trio 2 / Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO / dir24 / jnos110g.zip / PPPLCP.C < prev    next >
C/C++ Source or Header  |  1994-04-17  |  32KB  |  1,113 lines

  1. /*
  2.  *  PPPLCP.C    -- negotiate data link options
  3.  *
  4.  *  This implementation of PPP is declared to be in the public domain.
  5.  *
  6.  *  Jan 91  Bill_Simpson@um.cc.umich.edu
  7.  *      Computer Systems Consulting Services
  8.  *
  9.  *  Acknowledgements and correction history may be found in PPP.C
  10.  */
  11.   
  12. #include "global.h"
  13. #ifdef PPP
  14. #include "mbuf.h"
  15. #include "iface.h"
  16. #include "socket.h"
  17. #include "ppp.h"
  18. #include "pppfsm.h"
  19. #include "ppplcp.h"
  20. #include "ppppap.h"
  21. #include "cmdparse.h"
  22. #include "devparam.h"
  23. #include "trace.h"
  24.   
  25.   
  26. /* These defaults are defined in the PPP RFCs, and must not be changed */
  27. static struct lcp_value_s lcp_default = {
  28.     FALSE,      /* no need to negotiate defaults */
  29.   
  30.     LCP_MRU_DEFAULT,
  31.     LCP_ACCM_DEFAULT,
  32.     0,      /* no authentication */
  33.     0,      /* no encryption */
  34.     0L,     /* no magic number */
  35.     0L,     /* no reporting period */
  36. };
  37.   
  38. /* for test purposes, accept anything we understand in the NAK */
  39. static int16 lcp_negotiate = LCP_N_MRU | LCP_N_ACCM | LCP_N_AUTHENT
  40. | LCP_N_PFC | LCP_N_ACFC | LCP_N_MAGIC;
  41.   
  42. static byte_t option_length[] = {
  43.     0,     /* unused */
  44.     4,     /* MRU */
  45.     6,     /* ACCM */
  46.     4,     /* authentication */
  47.     4,     /* encryption */
  48.     6,     /* magic number */
  49.     6,     /* monitor reporting period */
  50.     2,     /* Protocol compression */
  51.     2      /* Address/Control compression */
  52. };
  53.   
  54.   
  55. static int dolcp_local      __ARGS((int argc, char *argv[], void *p));
  56. static int dolcp_open       __ARGS((int argc, char *argv[], void *p));
  57. static int dolcp_remote     __ARGS((int argc, char *argv[], void *p));
  58.   
  59. static int dolcp_accm       __ARGS((int argc, char *argv[], void *p));
  60. static int dolcp_acfc       __ARGS((int argc, char *argv[], void *p));
  61. static int dolcp_auth       __ARGS((int argc, char *argv[], void *p));
  62. static int dolcp_magic      __ARGS((int argc, char *argv[], void *p));
  63. static int dolcp_mru        __ARGS((int argc, char *argv[], void *p));
  64. static int dolcp_pfc        __ARGS((int argc, char *argv[], void *p));
  65. static int dolcp_default    __ARGS((int argc, char *argv[], void *p));
  66.   
  67. static void lcp_option __ARGS((struct mbuf **bpp,
  68. struct lcp_value_s *value_p,
  69. byte_t o_type,
  70. byte_t o_length,
  71. struct mbuf **copy_bpp ));
  72. static void lcp_makeoptions __ARGS((struct mbuf **bpp,
  73. struct lcp_value_s *value_p,
  74. int16 negotiating));
  75. static struct mbuf *lcp_makereq __ARGS((struct fsm_s *fsm_p));
  76.   
  77. static int lcp_check __ARGS((struct mbuf **bpp,
  78. struct lcp_s *lcp_p,
  79. struct lcp_side_s *side_p,
  80. struct option_hdr *option_p,
  81. int request));
  82.   
  83. static int lcp_request  __ARGS((struct fsm_s *fsm_p,
  84. struct config_hdr *config,
  85. struct mbuf *data));
  86. static int lcp_ack  __ARGS((struct fsm_s *fsm_p,
  87. struct config_hdr *ackcnf,
  88. struct mbuf *data));
  89. static int lcp_nak  __ARGS((struct fsm_s *fsm_p,
  90. struct config_hdr *nakcnf,
  91. struct mbuf *data));
  92. static int lcp_reject   __ARGS((struct fsm_s *fsm_p,
  93. struct config_hdr *rejcnf,
  94. struct mbuf *data));
  95.   
  96. static void lcp_reset   __ARGS((struct fsm_s *fsm_p));
  97. static void lcp_starting __ARGS((struct fsm_s *fsm_p));
  98. static void lcp_stopping __ARGS((struct fsm_s *fsm_p));
  99.   
  100. static void lcp_closing __ARGS((struct fsm_s *fsm_p));
  101. static void lcp_opening __ARGS((struct fsm_s *fsm_p));
  102.   
  103. static void lcp_free    __ARGS((struct fsm_s *fsm_p));
  104.   
  105.   
  106. static struct fsm_constant_s lcp_constants = {
  107.     "Lcp",
  108.     PPP_LCP_PROTOCOL,
  109.     0x0FFE,             /* codes 1-11 recognized */
  110.   
  111.     Lcp,
  112.     LCP_REQ_TRY,
  113.     LCP_NAK_TRY,
  114.     LCP_TERM_TRY,
  115.     LCP_TIMEOUT * 1000L,
  116.   
  117.     lcp_free,
  118.   
  119.     lcp_reset,
  120.     lcp_starting,
  121.     lcp_opening,
  122.     lcp_closing,
  123.     lcp_stopping,
  124.   
  125.     lcp_makereq,
  126.     lcp_request,
  127.     lcp_ack,
  128.     lcp_nak,
  129.     lcp_reject
  130. };
  131.   
  132.   
  133. /************************************************************************/
  134.   
  135. /* "ppp <iface> lcp" subcommands */
  136. static struct cmds Lcpcmds[] = {
  137.     "close",    doppp_close,    0,  0,  NULLCHAR,
  138.     "listen",   doppp_passive,  0,  0,  NULLCHAR,
  139.     "local",    dolcp_local,    0,  0,  NULLCHAR,
  140.     "open",     dolcp_open, 0,  0,  NULLCHAR,
  141.     "remote",   dolcp_remote,   0,  0,  NULLCHAR,
  142.     "timeout",  doppp_timeout,  0,  0,  NULLCHAR,
  143.     "try",      doppp_try,  0,  0,  NULLCHAR,
  144.     NULLCHAR,
  145. };
  146.   
  147. /* "ppp <iface> lcp [local | remote]" subcommands */
  148. static struct cmds Lcpside_cmds[] = {
  149.     "accm",     dolcp_accm, 0,  0,  NULLCHAR,
  150.     "acfc",     dolcp_acfc, 0,  0,  NULLCHAR,
  151.     "authenticate", dolcp_auth, 0,  0,  NULLCHAR,
  152.     "magic",    dolcp_magic,    0,  0,  NULLCHAR,
  153.     "mru",      dolcp_mru,  0,  0,  NULLCHAR,
  154.     "pfc",      dolcp_pfc,  0,  0,  NULLCHAR,
  155.     "default",  dolcp_default,  0,  0,  NULLCHAR,
  156.     NULLCHAR,
  157. };
  158.   
  159.   
  160. int
  161. doppp_lcp(argc,argv,p)
  162. int argc;
  163. char *argv[];
  164. void *p;
  165. {
  166.     register struct iface *ifp = p;
  167.     register struct ppp_s *ppp_p = ifp->edv;
  168.   
  169.     return subcmd(Lcpcmds, argc, argv, &(ppp_p->fsm[Lcp]));
  170. }
  171.   
  172.   
  173. static int
  174. dolcp_local(argc,argv,p)
  175. int argc;
  176. char *argv[];
  177. void *p;
  178. {
  179.     struct fsm_s *fsm_p = p;
  180.     struct lcp_s *lcp_p = fsm_p->pdv;
  181.     return subcmd(Lcpside_cmds, argc, argv, &(lcp_p->local));
  182. }
  183.   
  184.   
  185. static int
  186. dolcp_open(argc,argv,p)
  187. int argc;
  188. char *argv[];
  189. void *p;
  190. {
  191.     struct fsm_s *fsm_p = p;
  192.   
  193.     doppp_active( argc, argv, p );
  194.   
  195.     if ( fsm_p->ppp_p->phase >= pppLCP ) {
  196.         fsm_start( fsm_p );
  197.     }
  198.     return 0;
  199. }
  200.   
  201.   
  202. static int
  203. dolcp_remote(argc,argv,p)
  204. int argc;
  205. char *argv[];
  206. void *p;
  207. {
  208.     struct fsm_s *fsm_p = p;
  209.     struct lcp_s *lcp_p = fsm_p->pdv;
  210.     return subcmd(Lcpside_cmds, argc, argv, &(lcp_p->remote));
  211. }
  212.   
  213. /************************************************************************/
  214.   
  215. static int
  216. dolcp_accm(argc,argv,p)
  217. int argc;
  218. char *argv[];
  219. void *p;
  220. {
  221.     struct lcp_side_s *side_p = p;
  222.   
  223.     if (argc < 2) {
  224.         tprintf("0x%08lx\n",side_p->want.accm);
  225.     } else if (stricmp(argv[1],"allow") == 0) {
  226.         return bit16cmd(&(side_p->will_negotiate),LCP_N_ACCM,
  227.         "Allow ACCM", --argc, &argv[1] );
  228.     } else {
  229.         side_p->want.accm = strtoul(argv[1], NULLCHARP, 0);
  230.         if ( side_p->want.accm != LCP_ACCM_DEFAULT )
  231.             side_p->want.negotiate |= LCP_N_ACCM;
  232.         else
  233.             side_p->want.negotiate &= ~LCP_N_ACCM;
  234.     }
  235.     return 0;
  236. }
  237.   
  238.   
  239. static int
  240. dolcp_acfc(argc,argv,p)
  241. int argc;
  242. char *argv[];
  243. void *p;
  244. {
  245.     struct lcp_side_s *side_p = p;
  246.   
  247.     if (stricmp(argv[1],"allow") == 0) {
  248.         return bit16cmd(&(side_p->will_negotiate),LCP_N_ACFC,
  249.         "Allow Address/Control Field Compression", --argc, &argv[1] );
  250.     }
  251.     return bit16cmd( &(side_p->want.negotiate), LCP_N_ACFC,
  252.     "Address/Control Field Compression", argc, argv );
  253. }
  254.   
  255.   
  256. static int
  257. dolcp_auth(argc,argv,p)
  258. int argc;
  259. char *argv[];
  260. void *p;
  261. {
  262.     struct lcp_side_s *side_p = p;
  263.   
  264.     if (argc < 2) {
  265.         if ( side_p->want.negotiate & LCP_N_AUTHENT ) {
  266.             switch ( side_p->want.authentication ) {
  267.                 case PPP_PAP_PROTOCOL:
  268.                     tputs("Pap\n");
  269.                     break;
  270.                 default:
  271.                     tprintf("0x%04x\n", side_p->want.authentication);
  272.                     break;
  273.             };
  274.         } else {
  275.             tputs("None\n");
  276.         }
  277.     } else if (stricmp(argv[1],"allow") == 0) {
  278.         return bit16cmd(&(side_p->will_negotiate),LCP_N_AUTHENT,
  279.         "Allow Authentication", --argc, &argv[1] );
  280.     } else if (stricmp(argv[1],"pap") == 0) {
  281.         side_p->want.negotiate |= LCP_N_AUTHENT;
  282.         side_p->want.authentication = PPP_PAP_PROTOCOL;
  283.     } else if (stricmp(argv[1],"none") == 0) {
  284.         side_p->want.negotiate &= ~LCP_N_AUTHENT;
  285.     } else {
  286.         tputs("allow pap none\n");
  287.         return 1;
  288.     }
  289.     return 0;
  290. }
  291.   
  292.   
  293. static int
  294. dolcp_magic(argc,argv,p)
  295. int argc;
  296. char *argv[];
  297. void *p;
  298. {
  299.     struct lcp_side_s *side_p = p;
  300.     int result = 0;
  301.   
  302.     if (argc < 2) {
  303.         tprintf("%d\n",side_p->want.magic_number);
  304.     } else if (stricmp(argv[1],"allow") == 0) {
  305.         return bit16cmd(&(side_p->will_negotiate),LCP_N_MAGIC,
  306.         "Allow Magic Number", --argc, &argv[1] );
  307.     } else {
  308.         register int32 x = strtoul(argv[1], NULLCHARP, 0);
  309.   
  310.         if ( !x ) {
  311.             int test;
  312.   
  313.             /* Check for keyword */
  314.             result = setbool( &test, "Magic Number", argc, argv );
  315.   
  316.             if ( test ) {
  317.                 /* Make a non-zero random number */
  318.                 x = Clock << ((Clock & 0xf)+8);
  319.             }
  320.         }
  321.         if ( x ) {
  322.             side_p->want.negotiate |= LCP_N_MAGIC;
  323.         } else {
  324.             side_p->want.negotiate &= ~LCP_N_MAGIC;
  325.         }
  326.         side_p->want.magic_number = x;
  327.     }
  328.     return result;
  329. }
  330.   
  331.   
  332. static int
  333. dolcp_mru(argc,argv,p)
  334. int argc;
  335. char *argv[];
  336. void *p;
  337. {
  338.     struct lcp_side_s *side_p = p;
  339.   
  340.     if (argc < 2) {
  341.         tprintf("%d\n",side_p->want.mru);
  342.     } else if (stricmp(argv[1],"allow") == 0) {
  343.         return bit16cmd(&(side_p->will_negotiate),LCP_N_MRU,
  344.         "Allow MRU", --argc, &argv[1] );
  345.     } else {
  346.         register int x = (int)strtol( argv[1], NULLCHARP, 0 );
  347.   
  348.         if (x < LCP_MRU_LO || x > LCP_MRU_HI) {
  349.             tprintf("MRU %s (%d) out of range %d thru %d\n",
  350.             argv[1], x, LCP_MRU_LO, LCP_MRU_HI);
  351.             return -1;
  352.         } else if ( x != LCP_MRU_DEFAULT ) {
  353.             side_p->want.negotiate |= LCP_N_MRU;
  354.         } else {
  355.             side_p->want.negotiate &= ~LCP_N_MRU;
  356.         }
  357.         side_p->want.mru = x;
  358.     }
  359.     return 0;
  360. }
  361.   
  362.   
  363. static int
  364. dolcp_pfc(argc,argv,p)
  365. int argc;
  366. char *argv[];
  367. void *p;
  368. {
  369.     struct lcp_side_s *side_p = p;
  370.   
  371.     if (stricmp(argv[1],"allow") == 0) {
  372.         return bit16cmd(&(side_p->will_negotiate),LCP_N_PFC,
  373.         "Allow Protocol Field Compression", --argc, &argv[1] );
  374.     }
  375.     return bit16cmd( &(side_p->want.negotiate), LCP_N_PFC,
  376.     "Protocol Field Compression", argc, argv );
  377. }
  378.   
  379.   
  380. static int
  381. dolcp_default(argc,argv,p)
  382. int argc;
  383. char *argv[];
  384. void *p;
  385. {
  386.     struct lcp_side_s *side_p = p;
  387.   
  388.     ASSIGN( side_p->want, lcp_default );
  389.     return 0;
  390. }
  391.   
  392.   
  393. /************************************************************************/
  394. /*          E V E N T   P R O C E S S I N G         */
  395. /************************************************************************/
  396.   
  397. static void
  398. lcp_option( bpp, value_p, o_type, o_length, copy_bpp )
  399. struct mbuf **bpp;
  400. struct lcp_value_s *value_p;
  401. byte_t o_type;
  402. byte_t o_length;
  403. struct mbuf **copy_bpp;
  404. {
  405.     struct mbuf *bp;
  406.     register char *cp;
  407.     register int toss = o_length - OPTION_HDR_LEN;
  408.   
  409.     if ((bp = alloc_mbuf(o_length)) == NULLBUF) {
  410.         return;
  411.     }
  412.     cp = bp->data;
  413.     *cp++ = o_type;
  414.     *cp++ = o_length;
  415.   
  416.     switch ( o_type ) {
  417.         case LCP_MRU:
  418.             cp = put16(cp, value_p->mru);
  419.             toss -= 2;
  420. #ifdef PPP_DEBUG_OPTIONS
  421.             if (PPPtrace & PPP_DEBUG_OPTIONS)
  422.                 trace_log(PPPiface, "    making MRU: %d", value_p->mru);
  423. #endif
  424.             break;
  425.   
  426.         case LCP_ACCM:
  427.             cp = put32(cp, value_p->accm);
  428.             toss -= 4;
  429. #ifdef PPP_DEBUG_OPTIONS
  430.             if (PPPtrace & PPP_DEBUG_OPTIONS)
  431.                 trace_log(PPPiface, "    making ACCM: 0x%08lx", value_p->accm);
  432. #endif
  433.             break;
  434.   
  435.         case LCP_AUTHENT:
  436.             cp = put16(cp, value_p->authentication);
  437.             toss -= 2;
  438. #ifdef PPP_DEBUG_OPTIONS
  439.             if (PPPtrace & PPP_DEBUG_OPTIONS)
  440.                 trace_log(PPPiface, "    making Auth Protocol: 0x%04x",
  441.                 value_p->authentication);
  442. #endif
  443.             break;
  444.   
  445.         case LCP_MAGIC:
  446.             cp = put32(cp, value_p->magic_number);
  447.             toss -= 4;
  448. #ifdef PPP_DEBUG_OPTIONS
  449.             if (PPPtrace & PPP_DEBUG_OPTIONS)
  450.                 trace_log(PPPiface, "    making Magic Number: 0x%08lx",
  451.                 value_p->magic_number);
  452. #endif
  453.             break;
  454.   
  455.         case LCP_PFC:
  456. #ifdef PPP_DEBUG_OPTIONS
  457.             if (PPPtrace & PPP_DEBUG_OPTIONS)
  458.                 trace_log(PPPiface, "    making Protocol compression");
  459. #endif
  460.             break;
  461.   
  462.         case LCP_ACFC:
  463. #ifdef PPP_DEBUG_OPTIONS
  464.             if (PPPtrace & PPP_DEBUG_OPTIONS)
  465.                 trace_log(PPPiface, "    making Addr/Ctl compression");
  466. #endif
  467.             break;
  468.   
  469.         case LCP_ENCRYPT:       /* not implemented */
  470.         case LCP_QUALITY:       /* not implemented */
  471.         default:
  472. #ifdef PPP_DEBUG_OPTIONS
  473.             if (PPPtrace & PPP_DEBUG_OPTIONS)
  474.                 trace_log(PPPiface, "    making unimplemented type %d", o_type);
  475. #endif
  476.             break;
  477.     };
  478.   
  479.     while ( toss-- > 0 ) {
  480.         *cp++ = pullchar(copy_bpp);
  481.     }
  482.     bp->cnt += o_length;
  483.     append(bpp, bp);
  484. }
  485.   
  486.   
  487. /************************************************************************/
  488. /* Build a list of options */
  489. static void
  490. lcp_makeoptions(bpp, value_p, negotiating)
  491. struct mbuf **bpp;
  492. struct lcp_value_s *value_p;
  493. int16 negotiating;
  494. {
  495.     register int o_type;
  496.   
  497.     PPP_DEBUG_ROUTINES("lcp_makeoptions()");
  498.   
  499.     for ( o_type = 1; o_type <= LCP_OPTION_LIMIT; o_type++ ) {
  500.         if (negotiating & (1 << o_type)) {
  501.             lcp_option( bpp, value_p,
  502.             o_type, option_length[ o_type ], NULLBUFP);
  503.         }
  504.     }
  505. }
  506.   
  507.   
  508. /************************************************************************/
  509. /* Build a request to send to remote host */
  510. static struct mbuf *
  511. lcp_makereq(fsm_p)
  512. struct fsm_s *fsm_p;
  513. {
  514.     struct lcp_s *lcp_p = fsm_p->pdv;
  515.     struct mbuf *req_bp = NULLBUF;
  516.   
  517.     PPP_DEBUG_ROUTINES("lcp_makereq()");
  518.   
  519.     lcp_makeoptions( &req_bp, &(lcp_p->local.work),
  520.     lcp_p->local.work.negotiate );
  521.     return(req_bp);
  522. }
  523.   
  524.   
  525. /************************************************************************/
  526. /* Check the options, updating the working values.
  527.  * Returns -1 if ran out of data, ACK/NAK/REJ as appropriate.
  528.  */
  529. static int
  530. lcp_check( bpp, lcp_p, side_p, option_p, request )
  531. struct mbuf **bpp;
  532. struct lcp_s *lcp_p;
  533. struct lcp_side_s *side_p;
  534. struct option_hdr *option_p;
  535. int request;
  536. {
  537.     int toss = option_p->len - OPTION_HDR_LEN;
  538.     int option_result = CONFIG_ACK;     /* Assume good values */
  539.   
  540.     switch(option_p->type) {
  541.         case LCP_MRU:
  542.             side_p->work.mru = pull16(bpp);
  543.             toss -= 2;
  544. #ifdef PPP_DEBUG_OPTIONS
  545.             if (PPPtrace & PPP_DEBUG_OPTIONS)
  546.                 trace_log(PPPiface, "    checking MRU: %d", side_p->work.mru);
  547. #endif
  548.         /* Check if new value is appropriate */
  549.             if (side_p->work.mru < LCP_MRU_LO) {
  550.                 side_p->work.mru = LCP_MRU_LO;
  551.                 option_result = CONFIG_NAK;
  552.             } else if (side_p->work.mru > LCP_MRU_HI) {
  553.                 side_p->work.mru = LCP_MRU_HI;
  554.                 option_result = CONFIG_NAK;
  555.             }
  556.             if ( request && (side_p->want.negotiate & LCP_N_MRU)
  557.             && side_p->work.mru > side_p->want.mru ) {
  558.                 side_p->work.mru = side_p->want.mru;
  559.                 option_result = side_p->want.mru;
  560.             }
  561.             break;
  562.   
  563.         case LCP_ACCM:
  564.             side_p->work.accm = pull32(bpp);
  565.             toss -= 4;
  566. #ifdef PPP_DEBUG_OPTIONS
  567.             if (PPPtrace & PPP_DEBUG_OPTIONS)
  568.                 trace_log(PPPiface, "    checking ACCM: 0x%08lx", side_p->work.accm);
  569. #endif
  570.         /* Remote host may ask to escape more control  */
  571.         /* characters than we require, but must escape */
  572.         /* at least the control chars that we require. */
  573.             if ( (!request || (side_p->want.negotiate & LCP_N_ACCM))
  574.                 && side_p->work.accm !=
  575.             (side_p->work.accm | side_p->want.accm) ) {
  576.                 side_p->work.accm |= side_p->want.accm;
  577.                 option_result = CONFIG_NAK;
  578.             }
  579.             break;
  580.   
  581.         case LCP_AUTHENT:
  582.             side_p->work.authentication = pull16(bpp);
  583.             toss -= 2;
  584. #ifdef PPP_DEBUG_OPTIONS
  585.             if (PPPtrace & PPP_DEBUG_OPTIONS)
  586.                 trace_log(PPPiface, "    checking Auth Protocol: 0x%04x",
  587.                 side_p->work.authentication);
  588. #endif
  589.         /* Check if new value is appropriate */
  590.             switch ( side_p->work.authentication ) {
  591.                 case PPP_PAP_PROTOCOL:
  592.             /* Yes */
  593.                     break;
  594.                 default:
  595.                     side_p->work.authentication = PPP_PAP_PROTOCOL;
  596.                     option_result = CONFIG_NAK;
  597.                     break;
  598.             };
  599.             break;
  600.   
  601.         case LCP_MAGIC:
  602.             side_p->work.magic_number = pull32(bpp);
  603.             toss -= 4;
  604. #ifdef PPP_DEBUG_OPTIONS
  605.             if (PPPtrace & PPP_DEBUG_OPTIONS)
  606.                 trace_log(PPPiface, "    checking Magic Number: 0x%08lx",
  607.                 side_p->work.magic_number);
  608. #endif
  609.   
  610.         /* Ensure that magic numbers are different */
  611.             if (side_p->work.magic_number == 0L
  612.             || lcp_p->remote.work.magic_number == lcp_p->local.work.magic_number) {
  613.                 side_p->work.magic_number += Clock;
  614.                 option_result = CONFIG_NAK;
  615.             }
  616.             break;
  617.   
  618.         case LCP_PFC:
  619. #ifdef PPP_DEBUG_OPTIONS
  620.             if (PPPtrace & PPP_DEBUG_OPTIONS)
  621.                 trace_log(PPPiface, "    checking Protocol compression");
  622. #endif
  623.             break;
  624.   
  625.         case LCP_ACFC:
  626. #ifdef PPP_DEBUG_OPTIONS
  627.             if (PPPtrace & PPP_DEBUG_OPTIONS)
  628.                 trace_log(PPPiface, "    checking Addr/Ctl compression");
  629. #endif
  630.             break;
  631.   
  632.         case LCP_ENCRYPT:       /* not implemented */
  633.         case LCP_QUALITY:       /* not implemented */
  634.         default:
  635.             option_result = CONFIG_REJ;
  636.             break;
  637.     };
  638.   
  639.     if (option_p->type > LCP_OPTION_LIMIT
  640.     || !(side_p->will_negotiate & (1 << option_p->type))) {
  641.         option_result = CONFIG_REJ;
  642.     }
  643.   
  644.     if ( toss < 0 )
  645.         return -1;
  646.   
  647.     if ( !request  &&  toss > 0 ) {
  648.         /* toss extra bytes in option */
  649.         while( toss-- > 0 ) {
  650.             if ( pullchar(bpp) == -1 )
  651.                 return -1;
  652.         }
  653.     }
  654.   
  655.     return (option_result);
  656. }
  657.   
  658.   
  659. /************************************************************************/
  660. /* Check Link Control options requested by the remote host */
  661. static int
  662. lcp_request(fsm_p, config, data)
  663. struct fsm_s *fsm_p;
  664. struct config_hdr *config;
  665. struct mbuf *data;
  666. {
  667.     struct lcp_s *lcp_p = fsm_p->pdv;
  668.     int32 signed_length = config->len;
  669.     struct mbuf *reply_bp = NULLBUF;    /* reply packet */
  670.     int reply_result = CONFIG_ACK;      /* reply to request */
  671.     int16 desired;              /* desired to negotiate */
  672.     struct option_hdr option;       /* option header storage */
  673.     int option_result;          /* option reply */
  674.   
  675.     PPP_DEBUG_ROUTINES("lcp_request()");
  676.     lcp_p->remote.work.negotiate = FALSE;   /* clear flags */
  677.   
  678.     /* Process options requested by remote host */
  679.     while (signed_length > 0  &&  ntohopt(&option, &data) != -1) {
  680.         if ((signed_length -= option.len) < 0) {
  681.             PPP_DEBUG_CHECKS("LCP REQ: bad header length");
  682.             free_p(data);
  683.             free_p(reply_bp);
  684.             return -1;
  685.         }
  686.   
  687.         if ( ( option_result = lcp_check( &data, lcp_p,
  688.         &(lcp_p->remote), &option, TRUE ) ) == -1 ) {
  689.             PPP_DEBUG_CHECKS("LCP REQ: ran out of data");
  690.             free_p(data);
  691.             free_p(reply_bp);
  692.             return -1;
  693.         }
  694.   
  695. #ifdef PPP_DEBUG_OPTIONS
  696.         if (PPPtrace & PPP_DEBUG_OPTIONS) {
  697.             trace_log(PPPiface, "LCP REQ: result %s, option %d, length %d",
  698.             fsmCodes[option_result],
  699.             option.type,
  700.             option.len);
  701.         }
  702. #endif
  703.         if ( option_result < reply_result ) {
  704.             continue;
  705.         } else if ( option_result > reply_result ) {
  706.             /* Discard current list of replies */
  707.             free_p(reply_bp);
  708.             reply_bp = NULLBUF;
  709.             reply_result = option_result;
  710.         }
  711.   
  712.         /* remember that we processed option */
  713.         if ( option_result != CONFIG_REJ
  714.         && option.type <= LCP_OPTION_LIMIT ) {
  715.             lcp_p->remote.work.negotiate |= (1 << option.type);
  716.         }
  717.   
  718.         /* Add option response to the return list */
  719.         lcp_option( &reply_bp, &(lcp_p->remote.work),
  720.         option.type, option.len, &data );
  721.     }
  722.   
  723.     /* Now check for any missing options which are desired */
  724.     if ( fsm_p->retry_nak > 0
  725.         &&  (desired = lcp_p->remote.want.negotiate
  726.     & ~lcp_p->remote.work.negotiate) != 0 ) {
  727.         switch ( reply_result ) {
  728.             case CONFIG_ACK:
  729.                 free_p(reply_bp);
  730.                 reply_bp = NULLBUF;
  731.                 reply_result = CONFIG_NAK;
  732.             /* fallthru */
  733.             case CONFIG_NAK:
  734.                 lcp_makeoptions( &reply_bp, &(lcp_p->remote.want),
  735.                 desired );
  736.                 fsm_p->retry_nak--;
  737.                 break;
  738.             case CONFIG_REJ:
  739.             /* do nothing */
  740.                 break;
  741.         };
  742.     } else if ( reply_result == CONFIG_NAK ) {
  743.         /* if too many NAKs, reject instead */
  744.         if ( fsm_p->retry_nak > 0 )
  745.             fsm_p->retry_nak--;
  746.         else
  747.             reply_result = CONFIG_REJ;
  748.     }
  749.   
  750.     /* Send ACK/NAK/REJ to remote host */
  751.     fsm_send(fsm_p, reply_result, config->id, reply_bp);
  752.     free_p(data);
  753.     return (reply_result != CONFIG_ACK);
  754. }
  755.   
  756.   
  757. /************************************************************************/
  758. /* Process configuration ACK sent by remote host */
  759. static int
  760. lcp_ack(fsm_p, config, data)
  761. struct fsm_s *fsm_p;
  762. struct config_hdr *config;
  763. struct mbuf *data;
  764. {
  765.     struct mbuf *req_bp;
  766.     int error = FALSE;
  767.   
  768.     PPP_DEBUG_ROUTINES("lcp_ack()");
  769.   
  770.     /* ID field must match last request we sent */
  771.     if (config->id != fsm_p->lastid) {
  772.         PPP_DEBUG_CHECKS("LCP ACK: wrong ID");
  773.         free_p(data);
  774.         return -1;
  775.     }
  776.   
  777.     /* Get a copy of last request we sent */
  778.     req_bp = lcp_makereq(fsm_p);
  779.   
  780.     /* Overall buffer length should match */
  781.     if (config->len != len_p(req_bp)) {
  782.         PPP_DEBUG_CHECKS("LCP ACK: buffer length mismatch");
  783.         error = TRUE;
  784.     } else {
  785.         register int req_char;
  786.         register int ack_char;
  787.   
  788.         /* Each byte should match */
  789.         while ((req_char = pullchar(&req_bp)) != -1) {
  790.             if ((ack_char = pullchar(&data)) == -1
  791.             || ack_char != req_char ) {
  792.                 PPP_DEBUG_CHECKS("LCP ACK: data mismatch");
  793.                 /*trace_log(PPPiface, "req=%02X, ack=%02X", req_char, ack_char);*/
  794.                 error = TRUE;
  795.                 break;
  796.             }
  797.         }
  798.     }
  799.     free_p(req_bp);
  800.     free_p(data);
  801.   
  802.     if (error) {
  803.         return -1;
  804.     }
  805.   
  806.     PPP_DEBUG_CHECKS("LCP ACK: valid");
  807.     return 0;
  808. }
  809.   
  810.   
  811. /************************************************************************/
  812. /* Process configuration NAK sent by remote host */
  813. static int
  814. lcp_nak(fsm_p, config, data)
  815. struct fsm_s *fsm_p;
  816. struct config_hdr *config;
  817. struct mbuf *data;
  818. {
  819.     struct lcp_s *lcp_p = fsm_p->pdv;
  820.     struct lcp_side_s *local_p = &(lcp_p->local);
  821.     int32 signed_length = config->len;
  822.     struct option_hdr option;
  823.     int last_option = 0;
  824.     int result;
  825.   
  826.     PPP_DEBUG_ROUTINES("lcp_nak()");
  827.   
  828.     /* ID field must match last request we sent */
  829.     if (config->id != fsm_p->lastid) {
  830.         PPP_DEBUG_CHECKS("LCP NAK: wrong ID");
  831.         free_p(data);
  832.         return -1;
  833.     }
  834.   
  835.     /* First, process in order.  Then, process extra "important" options */
  836.     while (signed_length > 0  &&  ntohopt(&option, &data) != -1) {
  837.         if ((signed_length -= option.len) < 0) {
  838.             PPP_DEBUG_CHECKS("LCP NAK: bad header length");
  839.             free_p(data);
  840.             return -1;
  841.         }
  842.         if ( option.type > LCP_OPTION_LIMIT ) {
  843.             PPP_DEBUG_CHECKS("LCP NAK: option out of range");
  844.         } else if ( option.type < last_option
  845.         || !(local_p->work.negotiate & (1 << option.type)) ) {
  846.             if (local_p->work.negotiate & (1 << option.type)) {
  847.                 PPP_DEBUG_CHECKS("LCP NAK: option out of order");
  848.                 free_p(data);
  849.                 return -1;      /* was requested */
  850.             }
  851.             local_p->work.negotiate |= (1 << option.type);
  852.             last_option = LCP_OPTION_LIMIT + 1;
  853.         } else {
  854.             last_option = option.type;
  855.         }
  856.         if ( ( result = lcp_check( &data, lcp_p,
  857.         local_p, &option, FALSE ) ) == -1 ) {
  858.             PPP_DEBUG_CHECKS("LCP NAK: ran out of data");
  859.             free_p(data);
  860.             return -1;
  861.         }
  862.         /* update the negotiation status */
  863.         if ( result == CONFIG_REJ
  864.         && option.type <= LCP_OPTION_LIMIT ) {
  865.             local_p->work.negotiate &= ~(1 << option.type);
  866.         }
  867.     }
  868.     PPP_DEBUG_CHECKS("LCP NAK: valid");
  869.     free_p(data);
  870.     return 0;
  871. }
  872.   
  873.   
  874. /************************************************************************/
  875. /* Process configuration reject sent by remote host */
  876. static int
  877. lcp_reject(fsm_p, config, data)
  878. struct fsm_s *fsm_p;
  879. struct config_hdr *config;
  880. struct mbuf *data;
  881. {
  882.     struct lcp_s *lcp_p = fsm_p->pdv;
  883.     struct lcp_side_s *local_p = &(lcp_p->local);
  884.     int32 signed_length = config->len;
  885.     struct option_hdr option;
  886.     int last_option = 0;
  887.   
  888.     PPP_DEBUG_ROUTINES("lcp_reject()");
  889.   
  890.     /* ID field must match last request we sent */
  891.     if (config->id != fsm_p->lastid) {
  892.         PPP_DEBUG_CHECKS("LCP REJ: wrong ID");
  893.         free_p(data);
  894.         return -1;
  895.     }
  896.   
  897.     /* Process in order, checking for errors */
  898.     while (signed_length > 0  &&  ntohopt(&option, &data) != -1) {
  899.         register int k;
  900.   
  901.         if ((signed_length -= option.len) < 0) {
  902.             PPP_DEBUG_CHECKS("LCP REJ: bad header length");
  903.             free_p(data);
  904.             return -1;
  905.         }
  906.         if ( option.type > LCP_OPTION_LIMIT ) {
  907.             PPP_DEBUG_CHECKS("LCP REJ: option out of range");
  908.         } else if ( option.type < last_option
  909.         || !(local_p->work.negotiate & (1 << option.type))) {
  910.             PPP_DEBUG_CHECKS("LCP REJ: option out of order");
  911.             free_p(data);
  912.             return -1;
  913.         }
  914.         for ( k = option.len - OPTION_HDR_LEN; k-- > 0; ) {
  915.             if ( pullchar(&data) == -1 ) {
  916.                 PPP_DEBUG_CHECKS("LCP REJ: ran out of data");
  917.                 free_p(data);
  918.                 return -1;
  919.             }
  920.         }
  921.         last_option = option.type;
  922.   
  923.         if ( option.type <= LCP_OPTION_LIMIT ) {
  924.             local_p->work.negotiate &= ~(1 << option.type);
  925.         }
  926.     }
  927.     PPP_DEBUG_CHECKS("LCP REJ: valid");
  928.     free_p(data);
  929.     return 0;
  930. }
  931.   
  932.   
  933. /************************************************************************/
  934. /*          I N I T I A L I Z A T I O N         */
  935. /************************************************************************/
  936.   
  937. /* Check for PPP Network-Layer Protocol Phase */
  938. void
  939. ppp_ready(ppp_p)
  940. struct ppp_s *ppp_p;
  941. {
  942.     if ( !(ppp_p->flags & (PPP_AP_LOCAL | PPP_AP_REMOTE)) ) {
  943.         /* no pending authentication */
  944.         ppp_p->phase = pppREADY;
  945.   
  946.         ppp_p->upsince = secclock();
  947.         fsm_start( &(ppp_p->fsm[IPcp]) );
  948.     }
  949. }
  950.   
  951.   
  952. /****************************************************************************/
  953. /* Reset configuration options before request */
  954. static void
  955. lcp_reset(fsm_p)
  956. struct fsm_s *fsm_p;
  957. {
  958.     struct lcp_s *lcp_p =   fsm_p->pdv;
  959.   
  960.     PPP_DEBUG_ROUTINES("lcp_reset()");
  961.   
  962.     if ( lcp_p->local.want.negotiate & LCP_N_MAGIC ) {
  963.         lcp_p->local.want.magic_number += Clock;
  964.     }
  965.   
  966.     ASSIGN( lcp_p->local.work, lcp_p->local.want );
  967.     lcp_p->local.will_negotiate |= lcp_p->local.want.negotiate;
  968.   
  969.     lcp_p->remote.work.negotiate = FALSE;
  970.     lcp_p->remote.will_negotiate |= lcp_p->remote.want.negotiate;
  971. }
  972.   
  973.   
  974. /************************************************************************/
  975. /* Prepare to begin configuration exchange */
  976. static void
  977. lcp_starting(fsm_p)
  978. struct fsm_s *fsm_p;
  979. {
  980.     PPP_DEBUG_ROUTINES("lcp_starting()");
  981.   
  982.     fsm_p->ppp_p->phase = pppLCP;
  983. }
  984.   
  985.   
  986. /************************************************************************/
  987. /* After termination */
  988. static void
  989. lcp_stopping(fsm_p)
  990. struct fsm_s *fsm_p;
  991. {
  992.     struct iface *ifp = fsm_p->ppp_p->iface;
  993.   
  994.     PPP_DEBUG_ROUTINES("lcp_stopping()");
  995.   
  996.     /* Tell the dialer to shut down */
  997.     if ( ifp->supv != NULLPROC )
  998.         alert( ifp->supv, EABORT );
  999.   
  1000.     /* Now, tell the device to go down.
  1001.      * In turn, it should tell our IO status
  1002.      * when it has gone down.
  1003.      */
  1004.     ifp->ioctl(ifp,PARAM_DOWN,TRUE,0L);
  1005. }
  1006.   
  1007.   
  1008. /************************************************************************/
  1009. /* Close higher levels in preparation for link shutdown */
  1010. static void
  1011. lcp_closing(fsm_p)
  1012. struct fsm_s *fsm_p;
  1013. {
  1014.     struct ppp_s *ppp_p = fsm_p->ppp_p;
  1015.   
  1016.     ppp_p->phase = pppTERMINATE;
  1017.   
  1018.     fsm_down( &(ppp_p->fsm[IPcp]) );
  1019.     pap_down( &(ppp_p->fsm[Pap]) );
  1020. }
  1021.   
  1022.   
  1023. #ifdef TURBOC_SWITCH_BUG
  1024. #pragma option -G-
  1025. #endif
  1026.   
  1027. /************************************************************************/
  1028. /* configuration negotiation complete */
  1029. static void
  1030. lcp_opening(fsm_p)
  1031. struct fsm_s *fsm_p;
  1032. {
  1033.     struct lcp_s *lcp_p =   fsm_p->pdv;
  1034.     struct iface *ifp =     fsm_p->ppp_p->iface;
  1035.   
  1036.     if (ifp->mtu != lcp_p->remote.work.mru) {
  1037.         /* Set new Max Transmission Unit for outgoing packets */
  1038.         ifp->mtu = lcp_p->remote.work.mru;
  1039.         if (PPPtrace > 1)
  1040.             trace_log(PPPiface,"    Set new MTU for outgoing packets: %d",
  1041.             ifp->mtu);
  1042.     }
  1043.   
  1044.     /* check for authentication */
  1045.     fsm_p->ppp_p->phase = pppAP;
  1046.     fsm_p->ppp_p->flags &= ~(PPP_AP_LOCAL | PPP_AP_REMOTE);
  1047.     free(fsm_p->ppp_p->peername);
  1048.     fsm_p->ppp_p->peername = NULLCHAR;
  1049.   
  1050.     if (lcp_p->local.work.negotiate & LCP_N_AUTHENT) {
  1051.         switch (lcp_p->local.work.authentication) {
  1052.             case PPP_PAP_PROTOCOL:
  1053.                 pap_local(fsm_p->ppp_p);
  1054.                 break;
  1055.         };
  1056.     }
  1057.     if (lcp_p->remote.work.negotiate & LCP_N_AUTHENT) {
  1058.         switch (lcp_p->remote.work.authentication) {
  1059.             case PPP_PAP_PROTOCOL:
  1060.                 pap_remote(fsm_p->ppp_p);
  1061.                 break;
  1062.         };
  1063.     }
  1064.   
  1065.     /* re-check for authentication */
  1066.     ppp_ready(fsm_p->ppp_p);
  1067. }
  1068.   
  1069. #ifdef TURBOC_SWITCH_BUG
  1070. #pragma option -G
  1071. #endif
  1072.   
  1073.   
  1074. /************************************************************************/
  1075. static void
  1076. lcp_free(fsm_p)
  1077. struct fsm_s *fsm_p;
  1078. {
  1079.     /* nothing to do */
  1080. }
  1081.   
  1082.   
  1083. /* Initialize configuration structure */
  1084. void
  1085. lcp_init(ppp_p)
  1086. struct ppp_s *ppp_p;
  1087. {
  1088.     struct fsm_s *fsm_p = &(ppp_p->fsm[Lcp]);
  1089.     struct lcp_s *lcp_p;
  1090.   
  1091.     PPPtrace = ppp_p->trace;
  1092.     PPPiface = ppp_p->iface;
  1093.   
  1094.     PPP_DEBUG_ROUTINES("lcp_init()");
  1095.   
  1096.     fsm_p->ppp_p = ppp_p;
  1097.     fsm_p->pdc = &lcp_constants;
  1098.     fsm_p->pdv =
  1099.     lcp_p = callocw(1,sizeof(struct lcp_s));
  1100.   
  1101.     /* Set option parameters to first request defaults */
  1102.     ASSIGN( lcp_p->local.want, lcp_default );
  1103.     lcp_p->local.will_negotiate = lcp_negotiate;
  1104.   
  1105.     ASSIGN( lcp_p->remote.want, lcp_default );
  1106.     ASSIGN( lcp_p->remote.work, lcp_default );
  1107.     lcp_p->remote.will_negotiate = lcp_negotiate;
  1108.   
  1109.     fsm_init(fsm_p);
  1110. }
  1111. #endif /* PPP */
  1112.   
  1113.